using System;
using System.Diagnostics;
using System.Globalization;
using System.Windows.Forms;
using Schedulr.Configuration;
using Schedulr.Helpers;
using Schedulr.Properties;
using Schedulr.Tools;

namespace Schedulr
{
    /// <summary>
    /// The main form for this application.
    /// </summary>
    public partial class MainForm : Form
    {
        #region Constructor

        /// <summary>
        /// Initializes a new instance of the <see cref="MainForm"/> class.
        /// </summary>
        public MainForm()
        {
            InitializeComponent();
        }

        #endregion

        #region Event Handlers

        /// <summary>
        /// Handles the UndoChangesRequested event of the optionsEditor control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
        private void optionsEditor_UndoChangesRequested(object sender, EventArgs e)
        {
            SchedulrConfiguration.Invalidate();
            RefreshConfiguration();
        }

        #endregion

        #region Open & Close

        /// <summary>
        /// Handles the Shown event of the MainForm control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
        private void MainForm_Shown(object sender, EventArgs e)
        {
            Logger.Log("Initializing application.", TraceEventType.Information);
            // Set the version label.
            string version = "v" + AssemblyMilestoneAttribute.GetMilestoneFromAssembly();
            this.versionLabel.Text = version;

            UIActionScope.GlobalStatusControl = this.mainToolStripStatusLabel;
            FlickrServer.CurrentUserChanged += delegate { ShowUserDetails(); };

            using (UIActionScope scope = new UIActionScope("Logging in to Flickr..."))
            {
                // Initialize controls from configuration.
                SchedulrConfiguration.ConfigurationFileChanged += new EventHandler<EventArgs>(SchedulrConfiguration_ConfigurationFileChanged);
                SchedulrConfiguration.ConfigurationChanged += delegate { RefreshConfiguration(); };
                RefreshConfiguration();

                // Try to log in.
                FlickrServer.Login();
            }
        }

        /// <summary>
        /// Refreshes the configuration and populates the necessary controls.
        /// </summary>
        private void RefreshConfiguration()
        {
            SchedulrConfiguration configuration = SchedulrConfiguration.Instance;
            this.queuedPicturesEditor.Initialize(configuration.QueuedPictures);
            this.uploadedPicturesViewer.Initialize(configuration.UploadedPictures);
        }

        /// <summary>
        /// Handles the ConfigurationFileChanged event of the SchedulrConfiguration control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
        private void SchedulrConfiguration_ConfigurationFileChanged(object sender, EventArgs e)
        {
            if (this.InvokeRequired)
            {
                this.Invoke(new MethodInvoker(delegate { SchedulrConfiguration_ConfigurationFileChanged(sender, e); }));
            }
            else
            {
                string message = string.Format(CultureInfo.CurrentCulture, "The configuration has been changed by another process, probably because another instance of Schedulr was running in the background to upload the next picture in the queue.{0}{0}Do you want to reload the configuration to make sure the external changes aren't overwritten when this application is closed?", Environment.NewLine);
                DialogResult result = MessageBox.Show(this, message, "Reload configuration?", MessageBoxButtons.YesNo, MessageBoxIcon.Question);
                if (result == DialogResult.Yes)
                {
                    SchedulrConfiguration.Invalidate();
                    RefreshConfiguration();
                }
            }
        }

        /// <summary>
        /// Handles the FormClosing event of the MainForm control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.Windows.Forms.FormClosingEventArgs"/> instance containing the event data.</param>
        private void MainForm_FormClosing(object sender, FormClosingEventArgs e)
        {
            Logger.Log("Saving changes and closing application.", TraceEventType.Information);
            using (UIActionScope scope = new UIActionScope(null, Cursors.WaitCursor, "Saving changes...", this.mainToolStripStatusLabel))
            {
                SchedulrConfiguration.ConfigurationFileChanged -= new EventHandler<EventArgs>(SchedulrConfiguration_ConfigurationFileChanged);
                SchedulrConfiguration.Instance.Save();
                Settings.Default.Save();
            }
        }

        #endregion

        #region ShowUserDetails

        /// <summary>
        /// Shows the user details.
        /// </summary>
        private void ShowUserDetails()
        {
            UserInfo user = FlickrServer.CurrentUserInfo;
            if (user == null)
            {
                this.loginLinkLabel.Text = "Log in to Flickr";
            }
            else
            {
                this.loginLinkLabel.Text = "Logged in as " + user.UserName;
                if (FlickrServer.CurrentUserInfo.Pro)
                {
                    this.loginLinkLabel.Text += " (PRO)";
                }
                this.buddyIconPictureBox.ImageLocation = user.BuddyIconUrl;
                this.infoToolTip.SetToolTip(this.loginLinkLabel, user.PicturesUrl);
                this.userStatusLabel.Text = user.Status;
            }
        }

        #endregion

        #region Link Event Handlers

        /// <summary>
        /// Handles the LinkClicked event of the loginLinkLabel control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.Windows.Forms.LinkLabelLinkClickedEventArgs"/> instance containing the event data.</param>
        private void loginLinkLabel_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
        {
            if (FlickrServer.CurrentUserInfo == null)
            {
                using (UIActionScope scope = new UIActionScope("Logging in..."))
                {
                    // Log in to the server.
                    FlickrServer.Login();
                }
            }
            else
            {
                using (UIActionScope scope = new UIActionScope("Launching Flickr homepage"))
                {
                    if (!string.IsNullOrEmpty(FlickrServer.CurrentUserInfo.PicturesUrl))
                    {
                        Process.Start(FlickrServer.CurrentUserInfo.PicturesUrl);
                    }
                }
            }
        }

        /// <summary>
        /// Handles the LinkClicked event of the websiteLabel control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.Windows.Forms.LinkLabelLinkClickedEventArgs"/> instance containing the event data.</param>
        private void websiteLabel_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
        {
            // Execute the link with the system's default program.
            Process.Start(this.websiteLabel.Text);

            // Mark the link as visited.
            e.Link.Visited = true;
        }

        #endregion
    }
}